# -*- coding:utf-8 -*-
import cv2,os,time,re#,imageio
import numpy as np
from PIL import Image

'''
1.初始化视频属性：视频名称，编码格式，帧率，分辨率（宽，高）
2.遍历图片：把指定路径下的图片全路径存入集合list中
3.把图片宽高像素修改为一致的

'''
class GenVideo(object):

    def __init__(self,video_fps,video_width,video_height):
        self.video_writer = None
        self.video_fps = video_fps
        self.video_width = video_width
        self.video_height = video_height

    def getPicList(self,dirPath):
        picList = []
        for p in os.listdir(dirPath):
            full_p = os.path.join(dirPath,p)
            if os.path.isfile(full_p):
                picList.append(full_p)
        return picList

    def start(self,video_file_name):
        self.video_writer = cv2.VideoWriter(video_file_name,cv2.VideoWriter_fourcc(*'mp4v'),self.video_fps,(self.video_width,self.video_height),True)

    def record(self,img,extendType=None,value=None):
        imag = self.fixPic(img,extendType=extendType,value=value)
        self.video_writer.write(imag)
        return
        #res=cv2.resize(imag,(self.video_width,self.video_height),interpolation=cv2.INTER_CUBIC)
        #self.video_writer.write(res)
    
    def fixPic(self,img,extendType=None,value=None):
        #print(img)
        image = cv2.imread(img)
        #获取图片大小
        shap = image.shape #返回（高度，宽度，通道数）
        #若图片过大 需裁剪 
        height_deviation = self.video_height - shap[0]
        if height_deviation < 0 :
            #原图高度过大 需裁剪
            image = image[0:self.video_height,0:shap[1]]
            shap = image.shape #返回（高度，宽度，通道数）
        width_deviation = self.video_width - shap[1]
        if width_deviation < 0 :
            #原图宽度过大 需裁剪
            image = image[0:shap[0],0:self.video_width]
            shap = image.shape #返回（高度，宽度，通道数）
        #若图片不够尺寸 计算四周需要扩展的像素值（上，下，左，右）
        setoff = [0,0,0,0]
        if height_deviation > 0 :
            if  height_deviation % 2 == 0 :
                setoff[0] = height_deviation//2
                setoff[1] = setoff[0]
            else :
                setoff[0] = height_deviation//2
                setoff[1] = setoff[0]+1
        if width_deviation > 0 :
            if width_deviation % 2 == 0 :
                setoff[2] = width_deviation//2
                setoff[3] = setoff[2]
            else :
                setoff[2] = width_deviation//2
                setoff[3] = setoff[2]+1
        #扩展图片
        if extendType == 'constant' and value is not None:
            return cv2.copyMakeBorder(image,setoff[0],setoff[1],setoff[2],setoff[3],cv2.BORDER_CONSTANT,value=value) #指定扩展颜色value=[255,255,255]
        return cv2.copyMakeBorder(image,setoff[0],setoff[1],setoff[2],setoff[3],cv2.BORDER_REFLECT)
    '''
    图片加文字
    _source_pic 输入图像
    _target_pic 输出图片
    _text 需要添加的文字
    _place 左上角坐标
    _font 字体类型
    _font_size 字体大小
    _font_color 文字颜色
    _font_overstriking 字体粗细
    '''
    def addTextOnPic(self,_source_pic,_target_pic,_text,_place,_font,_font_size,_font_color,_font_overstriking):
        # 读入图片
        src = cv2.imread(_source_pic)
        #_font = cv2.FONT_HERSHEY_DUPLEX  # 设置字体
        #cv2.putText(AddText, text, (200, 100), cv2.FONT_HERSHEY_COMPLEX, 2.0, (100, 200, 200), 5)
        cv2.putText(src,_text, _place, _font, _font_size, _font_color, _font_overstriking)
        cv2.imwrite(_target_pic,src)

    '''
    两个图片叠加 pic1为背景图 pic2为前景图
    '''
    def addUpMultiPic(self,pic1,alph1,pic2,alph2,gamma=0):
        img1 = self.fixPic(pic1)
        img2 = self.fixPic(pic2)
        return cv2.addWeighted(img1,alph1,img2,alph2,gamma)

    def cutVideoToGif(self,video_file_path, gif_file_path, begin_seconds, end_seconds,
                         cut_border_pixels=0, zoom_rate=1, frame_pickup_internal=2, frame_duration=0.1):
        video_capture = cv2.VideoCapture(video_file_path)
     
        fps = video_capture.get(cv2.CAP_PROP_FPS)
        begin_frame_index = int(begin_seconds * fps)
        end_frame_index = int(end_seconds * fps)
     
        # set read from begin_frame_index
        video_capture.set(cv2.CAP_PROP_POS_FRAMES, begin_frame_index)
     
        index = 0
        frames = []
     
        while True:
            ret, image = video_capture.read()
     
            if ret is False:
                break
     
            index += 1
            if index <= end_frame_index - begin_frame_index:
                if index % frame_pickup_internal == 0:
                    cut_image = image[cut_border_pixels:(image.shape[0] - cut_border_pixels), 0:image.shape[1]]
     
                    width, height = cut_image.shape[0:2]
                    cut_image = cv2.resize(cut_image, (int(height * zoom_rate), int(width * zoom_rate)))
     
                    image_io_img = cv2.cvtColor(cut_image, cv2.COLOR_BGR2RGB)
                    frames.append(image_io_img)
            else:
                break
        #imageio.mimsave(gif_file_path, frames, 'GIF', duration=frame_duration)
        return frames

    def end(self):
        self.video_writer.release()

def displayImg(_window_name,_img):
    cv2.imshow(_window_name,_img)
    cv2.waitKey(0)
    cv2.destroyWindow(_window_name)

'''
处理图片尺寸
'''
def processFix():
    gv = GenVideo(video_fps,video_width,video_height)
    _p = 'C:/E/work_myself/python_study/process-img/chepai_bg/'
    plist = gv.getPicList(_p)
    #print(plist)
    gv.start('./%s us-chepai.mp4' % time.strftime("%Y-%m-%d %H%M%S ", time.localtime()))
    #_font = cv2.FONT_HERSHEY_DUPLEX  # 设置字体 暂时不知cv2怎么添加中文！！！
    for i in plist:
        #--------修改图片尺寸 begin-------------------#
        _temp = gv.fixPic(i)
        new_name = i.replace('chepai_bg','chepai_bg_fix')
        cv2.imwrite(new_name,_temp)
        #--------修改图片尺寸 end-------------------#
        #暂时不知cv2怎么添加中文！！！ gv.addTextOnPic(new_name,new_name.replace('.',' mask.'),'车牌',(10,20),_font,2.0,(255,255,255),5)

'''
合成视频
'''
def processGenVideo(_pics_path,_video_name,_if_extend=1):
    gv = GenVideo(video_fps,video_width,video_height)
    _p = _pics_path
    plist = gv.getPicList(_p)
    #print(plist)
    gv.start('%s %s' % (os.path.join(_pics_path,time.strftime("%Y-%m-%d %H%M%S ", time.localtime())),_video_name))
    for i in plist:
        #---------图片组成视频 begin-------------------#
        if _if_extend == 1 :
            gv.record(i) #若图片尺寸小于视频预设高宽则图片填充
        else :
            gv.record(i,extendType='constant',value=[0,0,0]) #若图片尺寸小于视频预设高宽则背景设置成黑色
        #---------图片组成视频 end-------------------#
    gv.end()
'''
根据正则替换字符
_exp:正则表达式
_repl:需要的字符
_str:要操作的字符串
'''
def altstr(_exp,_repl,_str):
    return re.sub(_exp,_repl,_str)
def reverseVideo():
    gv = GenVideo(12,video_width,video_height)
    dirp = r'E:/work_store/program/python/process-img/utility/pic/'
    plist = gv.getPicList(dirp)
    _index = len(plist)-1
    gv.start('./%s.mp4' % time.strftime("%Y-%m-%d %H%M%S ", time.localtime()))
    while _index >= 0:
        gv.record(dirp+str(_index)+'.png',extendType='constant',value=[0,0,0])
        _index -= 1
    gv.end()
'''
去水印
'''
def erasureWatermark(path,newPath):
    #dir = os.getcwd()
    img=cv2.imread(path,1)
    hight,width,depth=img.shape[0:3]
    #截取
    cropped = img[int(hight*0.8):hight, int(width*0.7):width]  # 裁剪坐标为[y0:y1, x0:x1]
    displayImg('cropped',cropped)
    cv2.imwrite(newPath, cropped)
    imgSY = cv2.imread(newPath,1)
    displayImg('imgSY',imgSY)
    #图片二值化处理，把[200,200,200]-[250,250,250]以外的颜色变成0
    thresh = cv2.inRange(imgSY,np.array([200,200,200]),np.array([250,250,250]))
    #创建形状和尺寸的结构元素
    kernel = np.ones((3,3),np.uint8)
    #扩展待修复区域
    hi_mask = cv2.dilate(thresh,kernel,iterations=10)
    specular = cv2.inpaint(imgSY,hi_mask,5,flags=cv2.INPAINT_TELEA)
    cv2.imwrite(newPath, specular)
    #覆盖图片
    imgSY = Image.open(newPath)
    img = Image.open(path)
    img.paste(imgSY, (int(width*0.7),int(hight*0.8),width,hight))
    img.save(newPath)
def get_water():
    # 黑底白字
    src = cv2.imread('yuan.png')  # 默认的彩色图(IMREAD_COLOR)方式读入原始图像
    # black.jpg
    mask = cv2.imread('di.png', cv2.IMREAD_GRAYSCALE)  # 灰度图(IMREAD_GRAYSCALE)方式读入水印蒙版图像
    # 参数：目标修复图像; 蒙版图（定位修复区域）; 选取邻域半径; 修复算法(包括INPAINT_TELEA/INPAINT_NS， 前者算法效果较好)
    dst = cv2.inpaint(src, mask, 3, cv2.INPAINT_NS)
    cv2.imwrite('result1.jpg', dst)
def get_water2():
    src = cv2.imread('yuan.png')
    mask = cv2.imread('di2.png')
    save = np.zeros(src.shape, np.uint8)  # 创建一张空图像用于保存
    for row in range(src.shape[0]):
        for col in range(src.shape[1]):
            for channel in range(src.shape[2]):
                if mask[row, col, channel] == 0:
                    val = 0
                else:
                    reverse_val = 255 - src[row, col, channel]
                    val = 255 - reverse_val * 256 / mask[row, col, channel]
                    if val < 0: val = 0
                save[row, col, channel] = val
    cv2.imwrite('result2.jpg', save)

video_width = 1920
video_height = 1080
video_fps = 0.4

PICS_SOURCE_DIR = 'C:/E/temp/pic/'
VIDEO_OUT_DIR = 'C:/E/temp/pic/'

#当前日期、时刻
import time,sys
file_name = time.strftime('%Y-%m-%d %H%M%S',time.localtime())

#平滑过渡
def smoothnessTransition(pic1,pic2):

    imga = cv2.imread(os.path.join(PICS_SOURCE_DIR,'1.jpg'))
    imgb = cv2.imread(os.path.join(PICS_SOURCE_DIR,'2.jpg'))
    fourcc = cv2.VideoWriter_fourcc('M', 'P', '4', 'V') #解码器
    out = cv2.VideoWriter(os.path.join(VIDEO_OUT_DIR,'out.mp4'), cv2.VideoWriter_fourcc(*'mp4v'), 30, (video_width, video_height), isColor=True)
    alphaValue = 0.0
    '''
    渐变前
    '''
    for i in range(120):
        out.write(imgb)       #加载2秒
    '''
    渐变中
    '''
    while alphaValue <= 1.0:
        imgout = cv2.addWeighted(imga, alphaValue, imgb, 1 - alphaValue, 0)
        alphaValue += 0.05
        out.write(imgout)
    '''
    渐变后
    '''
    for i in range(120):
        out.write(imga)       #加载两秒
    print("Saving...")
    out.release()
    print("Finish")

#缩小图片 参数为路径/文件名
def scalePic(img):
    image = cv2.imread(img)
    return scalePicObj(image)

#缩小图片 参数为图片对象
def scalePicObj(imgObj):
    #获取图片大小
    shap = imgObj.shape #返回（高度，宽度，通道数）
    img_height = shap[0]
    img_width = shap[1]
    scale_width = video_width/img_width
    scale_height = video_height/img_height
    #如果原图片尺寸小于预设值 不做处理直接返回
    if scale_width >= 1 and scale_height >=1:
        return imgObj
    #按最小比例缩放 保证图片完整
    big_scale_num = scale_width if scale_width < scale_height else scale_height
    xy_scale_num = scale_width if scale_width < scale_height else scale_height
    '''---后续按详细需求调整---'''
    x_scale_num = y_scale_num = xy_scale_num
    #若图片过大 缩小
    # 使用不同的插值调整图像大小
    #resize_cubic = cv2.resize(imgObj,(0, 0),fx=x_scale_num, fy=y_scale_num, interpolation = cv2.INTER_CUBIC)
    resize_area = cv2.resize(imgObj,(0, 0),fx=x_scale_num, fy=y_scale_num, interpolation = cv2.INTER_AREA)
    #resize_linear = cv2.resize(imgObj,(0, 0),fx=x_scale_num, fy=y_scale_num, interpolation = cv2.INTER_LINEAR)
    # 显示原始图像和调整大小后的图像
    #cv2.imwrite('bgcubic.jpg',resize_cubic)
    #cv2.imwrite('bgarea.jpg',resize_area)#用area这个方式
    #cv2.imwrite('bglinear.jpg',resize_linear)
    return resize_area

'''------临时代码 后期重构 begin-----'''
def fixPicTemp(img,extendType=None,value=None):
    #print(img)
    #image = cv2.imread(img)
    image = scalePic(img)
    #获取图片大小
    shap = image.shape #返回（高度，宽度，通道数）
    #若图片过大 需裁剪 
    height_deviation = video_height - shap[0]
    if height_deviation < 0 :
        #原图高度过大 需裁剪
        image = image[0:video_height,0:shap[1]]
        shap = image.shape #返回（高度，宽度，通道数）
    width_deviation = video_width - shap[1]
    if width_deviation < 0 :
        #原图宽度过大 需裁剪
        image = image[0:shap[0],0:video_width]
        shap = image.shape #返回（高度，宽度，通道数）
    #若图片不够尺寸 计算四周需要扩展的像素值（上，下，左，右）
    setoff = [0,0,0,0]
    if height_deviation > 0 :
        if  height_deviation % 2 == 0 :
            setoff[0] = height_deviation//2
            setoff[1] = setoff[0]
        else :
            setoff[0] = height_deviation//2
            setoff[1] = setoff[0]+1
    if width_deviation > 0 :
        if width_deviation % 2 == 0 :
            setoff[2] = width_deviation//2
            setoff[3] = setoff[2]
        else :
            setoff[2] = width_deviation//2
            setoff[3] = setoff[2]+1
    #扩展图片
    if extendType == 'constant' and value is not None:
        return cv2.copyMakeBorder(image,setoff[0],setoff[1],setoff[2],setoff[3],cv2.BORDER_CONSTANT,value=value) #指定扩展颜色value=[255,255,255]
    return cv2.copyMakeBorder(image,setoff[0],setoff[1],setoff[2],setoff[3],cv2.BORDER_REFLECT)

def smoothnessTransitionProcess(_pics_path,_video_name,_if_extend=1):
    out = cv2.VideoWriter(os.path.join(VIDEO_OUT_DIR,'out.mp4'), cv2.VideoWriter_fourcc(*'mp4v'), 60, (video_width, video_height), isColor=True)
    duration_frame = 120
    picList = []
    for p in os.listdir(PICS_SOURCE_DIR):
        full_p = os.path.join(PICS_SOURCE_DIR,p)
        if os.path.isfile(full_p):
            picList.append(full_p)
    maxNum = len(picList)
    for i in range(maxNum):
        if i+1 == maxNum :
            break
        imga = cv2.imread(picList[i])
        imgb = cv2.imread(picList[i+1])
        if i == 0:
            for i in range(duration_frame):
                out.write(imga)       #第一张图片需要先加载(duration_frame/fps=x)x秒
        '''
        渐变前
        '''
        for i in range(duration_frame):
            out.write(imga)       #加载(duration_frame/fps=x)x秒
        '''
        渐变中
        '''
        alphaValue = 0.0
        while alphaValue <= 1.0:
            imgout = cv2.addWeighted(imgb, alphaValue, imga, 1 - alphaValue, 0)
            alphaValue += 0.05
            out.write(imgout)
        '''
        渐变后
        '''
        if i == maxNum-2:#已到最后一张图 首位对应时长
            duration_frame = duration_frame * 2
        for i in range(duration_frame):
            out.write(imgb)       #加载(duration_frame/fps=x)x秒
    out.release()
'''------临时代码 后期重构 end-----'''

def smoothnessTransitionMain():
    duration_frame = 5
    picList = []
    for p in os.listdir(PICS_SOURCE_DIR):
        full_p = os.path.join(PICS_SOURCE_DIR,p)
        if os.path.isfile(full_p):
            picList.append(full_p)
    maxNum = len(picList)
    out = cv2.VideoWriter(os.path.join(VIDEO_OUT_DIR,'out.mp4'),cv2.VideoWriter_fourcc(*'mp4v'),20,(video_width, video_height),isColor=True)
    for i in range(maxNum):
        if i+1 == maxNum :
            break
        imga = fixPicTemp(picList[i])
        imgb = fixPicTemp(picList[i+1])
        if i == 0:
            for i in range(duration_frame):
                out.write(imga)       #第一张图片需要先加载(duration_frame/fps=x)x秒
        '''
        渐变前
        '''
        for i in range(duration_frame):
            out.write(imga)       #加载(duration_frame/fps=x)x秒
        '''
        渐变中
        '''
        alphaValue = 0.0
        while alphaValue <= 1.0:
            imgout = cv2.addWeighted(imgb, alphaValue, imga, 1 - alphaValue, 0)
            alphaValue += 0.1
            out.write(imgout)
        '''
        渐变后
        '''
        if i == maxNum-2:#已到最后一张图 首位对应时长
            duration_frame = duration_frame * 2
        for i in range(duration_frame):
            out.write(imgb)       #加载(duration_frame/fps=x)x秒
    out.release()

def slipTransitionMain():
    #out = cv2.VideoWriter(os.path.join(VIDEO_OUT_DIR,'out.mp4'), cv2.VideoWriter_fourcc(*'mp4v'), 30, (video_width, video_height), isColor=True)
    imga = cv2.imread(os.path.join(PICS_SOURCE_DIR,'1.jpg'))
    imgb = cv2.imread(os.path.join(PICS_SOURCE_DIR,'2.jpg'))
    rows,cols = imga.shape[0],imga.shape[1]
    #M = np.float32([[1,0,-960],[0,1,0]]) #(x轴 宽列，y轴 高行)
    #dsta = cv2.warpAffine(imga,M,(cols,rows))
    #-----移动图片 begin-----#
    duration = 0
    while duration <= -1:
        M = np.float32([[1,0,-10*duration],[0,1,0]]) #(x轴 宽列，y轴 高行)
        dsta = cv2.warpAffine(imga,M,(cols,rows))
        #out.write(dsta)
        duration += 1
    #-----移动图片 end-----#
    #-----裁剪图片 begin-----#
    dsta = imga[0:1080, 0:959] # 裁剪坐标为[y0:y1, x0:x1]
    dstb = imgb[0:1080, 960:1920] # 裁剪坐标为[y0:y1, x0:x1]
    #-----裁剪图片 end-----#
    #-----拼接图片 begin-----#
    #dstc = np.hstack((dsta,dstb))
    dstc = cv2.hconcat([dsta,dstb])
    #-----拼接图片 end-----#
    #out.release()
    #cv2.imshow('img',dsta)
    #cv2.waitKey(0)
    #cv2.imshow('img',dstb)
    cv2.imshow('img',dstc)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

#截取视频帧为图片
def cutPictureFromVideoMain(video_file,image_path,imag_count,start_frame=1,end_frame=0):
    cap = cv2.VideoCapture(video_file)
    #获取视频总帧数
    frame_count = end_frame
    if end_frame == 0 :
        frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
    print("frame count:",frame_count)
    #截图时帧的间距,这里是等距离截取imag_count张图
    frame_interval = int(frame_count // imag_count)
    #起始截取帧位置
    #start_frame = 1
    #截图存储位置
    #image_path = ''

    flag = 0
    while(cap.isOpened()):
        cap.set(cv2.CAP_PROP_POS_MSEC,flag)
        cap.set(cv2.CAP_PROP_POS_FRAMES,start_frame)
        #print('current frame:',start_frame)
        ret,img = cap.read()
        #cv2.waitKey(2000)
        cv2.imwrite((image_path + file_name + '{}.jpg').format('{:0>3d}'.format(flag)),img)
        flag += 1
        start_frame += frame_interval
        if start_frame >= frame_count:
            break
    cap.release()
    cv2.destroyAllWindows()

#只处理图片，不生成视频
def processPicMain(image_target_path):
    flag = 0
    for p in os.listdir(PICS_SOURCE_DIR):
        full_p = os.path.join(PICS_SOURCE_DIR,p)
        if os.path.isfile(full_p):
            img = fixPicTemp(full_p)
            cv2.imwrite((image_target_path + file_name + ' extend_{}.jpg').format('{:0>3d}'.format(flag)),img)
            flag += 1
    cv2.destroyAllWindows()

#检测重复图片
import shutil
def checkRepeatPic(dirroot):
    finallpics = []
    repeatpics = []
    current_name = ''
    current_index = 0
    sum = 0
    pics = os.listdir(dirroot)
    picsum = len(pics)
    for index in range(picsum-1):
        #if sum > 10 :
        #    break
        p1 = cv2.imread(os.path.join(dirroot,pics[index]))
        p2 = cv2.imread(os.path.join(dirroot,pics[index+1]))
        different = cv2.subtract(p1,p2)
        #result = not np.any(different) #若图片相同 np.any(a,b)会返回false
        #print(pics[index],pics[index+1],result,np.max(different))
        if np.max(different) < 200:
            repeatpics.append(pics[index+1])
        sum += 1
    print(repeatpics)
    for p in repeatpics:
        shutil.move(dirroot+p,'C:/E/temp/pic/repeatjddbjd/'+p)


if __name__ == '__main__':
    try:
        pass
        #cv2.imwrite('C:/E/temp/pic/1area.jpg',scalePic('C:/E/temp/pic/1.jpg'))
        #processFix()
        #processGenVideo(PICS_SOURCE_DIR,'pics_video.mp4')
        #reverseVideo()
        #erasureWatermark("1.jpeg","new.jpg")
        smoothnessTransitionMain()
        #slipTransitionMain()
        #cutPictureFromVideoMain('C:/E/temp/pic/guijiao_Trim.mp4',PICS_SOURCE_DIR+'guijiao_Trim/',210,start_frame=1)
        #processPicMain(PICS_SOURCE_DIR)
        #checkRepeatPic('C:/E/temp/pic/jiandandebujiandanB/')
    except Exception as ex:
        print('Found error:%s' % str(ex))
